home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 10
/
FM Towns Free Software Collection 10.iso
/
ms_dos
/
lib
/
happysrc
/
pimain.c
< prev
next >
Wrap
Text File
|
1994-11-13
|
16KB
|
427 lines
/************************************************
**
** *** HAPPy P-code Interpreter ***
**
** メイン処理
**
** Copyright (c) H.Asano. 1992-1994.
************************************************/
#define EXTERN
#include <signal.h>
#include <process.h>
#include <io.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <float.h>
#include "version.h"
#include "hapai.h"
#define abnormal 1 /* usage関数への引数 */
#define normal 0 /* usage関数への引数 */
extern void interpret(void) ; /* P-code命令解釈実行処理 */
_store store[Maxstore] ; /* 記憶装置 */
_store *sp ; /* stack pointer */
short pc ; /* program counter */
short mp ; /* begginning of a data segment */
short ep ; /* the maxmum extent of the stack */
short np ; /* top of the dynamically allocated area */
_code cd ; /* P-code */
short fileno ; /* ファイル数 */
boolean trace ; /* 命令トレースフラグ */
boolean readlnflag = true ; /* 起動時及びinputにreadlnをした時 真 */
const char *ext = ".pco" ; /* P-codeオプジェクトファイルの拡張子 */
static char pcofname[50] ; /* P-codeオブジェクトファイル名 */
static char progname[33] ; /* Pascalプログラム名 */
static short objsize ;
static FILE *pcofile ;
static boolean infor = false ; /* -iオプション インタプリタ情報出力 */
static boolean fileoptflag = false ; /* /fオプション ファイル名指定 */
static short fno ; /* /fオプションで取得したファイル数 */
static int wargc ; /* argc 退避 */
static char **wargv ; /* argv 退避 */
/******************************************/
/* puteoln() : 終了時のeoln付与処理 */
/******************************************/
void puteoln(void)
{
short i ;
for(i=0;i<fileno;i++) { /* ファイルクローズを行う */
if((fi[i].mode == generation) && /* 生成モードでテキストで */
(fi[i].textfile) && (!fi[i].writelnflag)) /* 最後が改行でない*/
fputc('\n',fi[i].fp) ; /* 改行を付け加える */
fclose(fi[i].fp) ; /* エラーチェックはしない */
}
}
/******************************/
/* title() : タイトル表示処理 */
/******************************/
static void title(void)
{
static putflag = false ;
if(!putflag) { /* 一度だけ表示する */
fprintf(stderr,
"HAPPy P-code Interpreter Version %s Copyright (c) H.Asano 1992-1994.\n",
version) ;
putflag = true ;
}
}
/******************************************/
/* prerr() : Run-timeエラーメッセージ出力 */
/******************************************/
void prerr(short errno,char *msg)
{
fprintf(stderr,"\n*** [ADDR=%d] HAPPy Run-time error R%03d:\n -- %s",
pc-1,errno,msg) ;
fputs(" : 処理打ち切り ***\n",stderr);
puteoln() ; /* ファイルクローズ & eoln付与*/
exit(1) ; /* ランタイムエラーで終了 */
}
/**********************************************/
/* pierr() : インタプリタエラーメッセージ出力 */
/**********************************************/
static void pierr(char *msg, char *umecomi)
{
title() ;
fprintf(stderr,msg,umecomi) ;
exit(2) ; /* その他のエラーで終了 */
}
/****************************************/
/* cntl_c(): cntl_cが押された時の処理 */
/****************************************/
static void cntl_c(int sig, int subcode)
{
prerr(152,"<CTRL-C>を受け付けた");
}
/****************************************/
/* real_err(): 浮動小数点例外 */
/****************************************/
static void real_err(int sig, int subcode)
{
char *type ;
char buf[80] ;
switch(subcode) {
case FPE_INVALID : type = "invalid"; break ;
case FPE_OVERFLOW : type = "overflow"; break ;
case FPE_STACKOVERFLOW : type = "stack overflow"; break ;
case FPE_STACKUNDERFLOW : type = "stack underflow"; break ;
}
sprintf(buf,"実数演算で異常が起きた(%s)",type) ;
prerr(150,buf) ;
}
/******************************/
/* usage() : 使用方法出力処理 */
/******************************/
static void usage(short type)
{
title() ;
if(type==abnormal) fputs("\nI004: 起動パラメータが誤っている\n",stderr);
else { /* pi のみで アーギュメントなしの時 */
fputs("\n HAPPy is the H.Asano Pascal Processing system. (^_^)\n",
stderr);
fputs(
"\n HAPPyはISO7185規格水準0にほぼ準拠したMS-DOS汎用Pascal処理系です。\n",
stderr) ;
fputs(" HAPPyの複写・再配付は自由です。\n", stderr) ;
}
fputs("\n piコマンドはpcコマンドで作ったP-codeオブジェクトを実行します。\n\n",stderr);
fputs(" 使い方: pi [ オプション...] P-codeオブジェクトファイル名[.pco] [ オプション...]\n",
stderr) ;
fputs(" オプション:\n",stderr);
fputs(" -i ・・・ インタプリタ情報を出力する\n",stderr);
fputs(" -t ・・・ トレースをを標準出力に出力する\n",stderr);
fputs(" /f ・・・ プログラム引数のファイル名と実ファイル名を対応させる\n",
stderr);
fputs(" 例: /fputfile=h:\\work\\list.txt\n",stderr) ;
exit(2) ;
}
/************************************/
/* information() : -iオプション処理 */
/************************************/
static void information(void)
{
short i,j ;
short max = 0 ;
title() ;
fprintf(stderr,"\n * Program name = %s\n",progname) ;
fprintf(stderr," * Total memory = %5d words\n",Maxstore) ;
fprintf(stderr," * Object size = %5d words\n",objsize) ;
fprintf(stderr," * stack/heap = %5d words\n",Maxstore-objsize) ;
if(fileno!=2) {
fputs(" * input,output以外のファイルと実ファイルの対応\n",stderr) ;
for(i=2;i<fileno;i++)
if(strlen(fi[i].filename) > max) max = strlen(fi[i].filename) ;
for(i=2;i<fileno;i++) {
fprintf(stderr," %s",fi[i].filename) ;
for(j=strlen(fi[i].filename);j<max;j++)
fputc(' ',stderr) ; /* 最大の長さに合わせるため */
fprintf(stderr," = %s\n",fi[i].rfname) ;
}
}
fputc('\n',stderr) ;
}
/******************************************/
/* fileoption() : ファイルオプション処理 */
/******************************************/
static void fileoption(char *fileopt)
{
short i=0 ;
short j ;
short len ;
char logicalf[MaxIDlng+1] ; /* プログラム上のファイル名 */
if(fileno==2) usage(abnormal) ; /* ファイル未使用時 /f は 指定不可*/
while(*(fileopt+i)!='=') i++ ; /* プログラム上のファイル名取得*/
if(i>MaxIDlng) i=MaxIDlng ;
for(j=0;j<i;j++)
logicalf[j] = (char)tolower(*(fileopt+j)) ;
logicalf[i] = '\0' ;
j=2;
while((j<fileno) &&
strcmp(fi[j].filename,logicalf)) j++ ;
if(j==fileno) { /* プログラム上で使われていない時*/
title() ;
fprintf(stderr,"I005:/fオプション(%s)無効 : 無視する\n",fileopt) ;
return ;
}
if(fi[j].askflag) { /* まだ/fオプションで未処理のファイル */
fi[j].askflag = false ;
fno++ ; /* /fオプション で 指定したファイル数 */
}
len = strlen(fileopt)-i-1 ;
if(len > MaxRFlen) len = MaxRFlen ;
strncpy(fi[j].rfname,fileopt+i+1,len) ;
fi[j].rfname[len] = '\0' ;
}
/*****************************************/
/* inputfilename() : ファイル名入力処理 */
/*****************************************/
static void inputfilename(void)
{
short i,j ;
short ch ;
title() ;
fputs("*HAPPy: ファイル( ",stderr) ;
for(i=2;i<fileno;i++)
if(fi[i].askflag) fprintf(stderr,"%s ",fi[i].filename) ;
fputs(")の実ファイル名を入力して下さい\n",stderr);
for(i=2;i<fileno;i++)
if(fi[i].askflag) {
fprintf(stderr," %s : ",fi[i].filename) ;
while(((ch=getc(stdin)) == ' ') || (ch == '\t'));
/* 空白,タブの読み飛ばし */
j = 0 ;
while(ch != '\n') {
fi[i].rfname[j++] = (char)ch ;
if(j == MaxRFlen) break ;
ch = getc(stdin) ;
} ;
fi[i].rfname[j] = '\0' ;
}
fputs("*HAPPy: ファイル名入力終了 *\n\n",stderr) ;
}
/***************************************/
/* fcheck() : ファイルチェック処理 */
/***************************************/
static void fcheck(void)
{
if(feof(pcofile)) /* 途中でファイルが終わってしまった*/
pierr("I002: P-codeオブジェクトファイル(%s)が不当である",pcofname) ;
}
/***************************************/
/* init() : 初期設定処理 */
/***************************************/
static void init(void)
{
short i ;
char ch ;
short headerlen ; /* ヘッダ部分の長さ */
char compversion[6] ; /* コンパイラバージョン番号 */
/**** input,outputファイルのファイル情報を設定する ****/
strcpy(fi[0].filename,"input") ;
fi[0].fileadr = inputadr ;
fi[0].filesize = 1 ;
strcpy(fi[0].rfname,"標準入力") ;
fi[0].fp = stdin ; /* 標準入力 */
fi[0].mode = inspection ; /* 検査モード */
fi[0].textfile = true ; /* テキストファイル */
strcpy(fi[1].filename,"output") ;
fi[1].fileadr = outputadr ;
fi[1].filesize = 1 ;
strcpy(fi[1].rfname,"標準出力") ;
fi[1].fp = stdout ; /* 標準出力 */
fi[1].mode = generation ; /* 生成モード */
fi[1].textfile = true ; /* テキストファイル */
fi[1].writelnflag = true ;
fileno = fno = 2 ;
objsize = (short)filelength(fileno(pcofile));
i = 0 ;
do { /* バージョン番号を読む */
ch = (char)fgetc(pcofile) ;
fcheck() ;
} while((compversion[i++]=ch)) ;
headerlen = i ;
if(strcmp(compversion,version))
pierr(
"I003: コンパイラ(Version %s)とバージョンが一致しない\n",compversion) ;
i = 0 ;
do { /* プログラム名を読む */
progname[i] = (char)fgetc(pcofile) ;
fcheck() ;
} while(progname[i++]) ;
headerlen += i ;
while((fi[fileno].fileadr = getw(pcofile)) != -1) {
fcheck() ;
headerlen += sizeof(short) ;
fi[fileno].filesize = getw(pcofile) ; /* バッファ変数の大きさ */
headerlen += sizeof(short) ;
i = 0 ;
do { /* ファイル名を読む */
fi[fileno].filename[i] = (char)fgetc(pcofile) ;
fcheck() ;
} while(fi[fileno].filename[i++]) ;
fi[fileno].mode = undefined ; /* ファイルモードは不定 */
fi[fileno].askflag = true ; /* ファイル名問い合わせ要としておく*/
fi[fileno].textfile = false ; /* テキストでないとしておく */
headerlen += i ;
fileno++ ;
}
fcheck() ;
headerlen += sizeof(short) ;
objsize -= headerlen ;
fread((char*)store,objsize,1,pcofile) ; /* P-codeオブジェクトを読む*/
objsize /= sizeof(_store) ;
for(i=0;i<fileno;i++) {
fi[i].fileadr += objsize ; /* ファイルアドレスの修正 */
fi[i].filebuf = store + fi[i].fileadr ; /* バッファ変数アドレス*/
}
}
/******************************************/
/* main() : P-codeインタプリタメイン処理 */
/******************************************/
void main(int argc,char **argv)
{
short i,j ;
boolean getfileflag = false ;
wargc = argc ;
wargv = argv ;
if(argc < 2) usage(normal); /* アーギュメントなしはusage */
while(--argc) { /* オプションの処理 */
if(**++argv == '-') {
for(i=1;*(*argv+i)!='\0';i++)
switch(*(*argv+i)) {
case 'I' :
case 'i' : infor = true ; /* information option */
break ;
case 'T' :
case 't' : trace = true ; /* trace option */
break ;
default : usage(abnormal); /* -t -i 以外はエラー */
}
if(i==1) usage(abnormal); /* - だけの時はusage */
}
else if(**argv == '/') {
if((*(*argv+1) == 'f') || (*(*argv+1) == 'F')) {
j=2 ;
while((*(*argv+j)) && /* /f・・・・=・・・・・ であること */
(*(*argv+j)!='=')) j++ ; /* をチェックする */
if((*(*argv+j)!='=') || /* = がない */
!(*(*argv+j+1)) || /* = で終わっている */
(j==2)) usage(abnormal) ; /* /f のみ */
fileoptflag = true ; /* /fオプション あり */
}
}
else { /* - / から始まらないアーギュメント */
if(getfileflag) { /* すでにソースファイル名を */
usage(abnormal); /* 取得している時は 誤り */
break ; /* whileループ脱出 */
}
getfileflag = true ; /* ファイル名取得済とする */
*pcofname = '\0' ;
strcpy(pcofname, *argv) ;
j=0 ; /* 拡張子が省略されているか */
while((*(pcofname+j)!='\0') && (*(pcofname+j)!='.')) j++ ;
if(*(pcofname+j)=='\0') strcat(pcofname,ext) ; /* 拡張子を付与 */
}
}
if(getfileflag) { /* ファイル名が指定された時 */
pcofile = fopen(pcofname,"rb");
if(pcofile==NULL)
pierr("I001: P-codeオブジェクトファイル(%s)がない\n",pcofname);
}
else usage(abnormal) ; /* ファイル名の指定がない時 */
init() ; /* 各種初期設定 */
if(fileoptflag) /* /fオプションあり */
while(--wargc)
if(**++wargv == '/')
if((*(*wargv+1) == 'f') || (*(*wargv+1) == 'F'))
fileoption(*wargv+2) ;
if(fileno!=fno) inputfilename() ; /* 全ファイルが決定していない時 */
if(infor) information() ; /* -i インタプリタ情報出力 */
signal(SIGINT,cntl_c) ; /* CTRL-Cシグナル登録 */
signal(SIGFPE,real_err) ; /* 実数演算シグナル登録 */
pc = 0 ; /* Program Counter 初期設定 */
mp = objsize ; /* mp 初期設定 */
ep = mp + 5 ; /* ep 初期設定 */
np = Maxstore ; /* np 初期設定 */
sp = store+mp-1 ; /* Stack Pointer 初期設定 */
interpret() ; /* P-code命令解釈実行 */
}